import * as cryptoService from 'crypto-js';
var db = window.sqlitePlugin.openDatabase({
    name: 'device.db',
    location: 'default',
    androidDatabaseProvider: 'system'
});

db.transaction(function (tx) {
    tx.executeSql('CREATE TABLE IF NOT EXISTS uses (code text PRIMARY KEY  NOT NULL,count text)');
});
export function init() {
    db.transaction(function (tx) {
        tx.executeSql('CREATE TABLE IF NOT EXISTS history (code text PRIMARY KEY  NOT NULL)');
        tx.executeSql('CREATE TABLE IF NOT EXISTS productrule (id INT PRIMARY KEY NOT NULL, name text, showrule text)');
        tx.executeSql('CREATE TABLE IF NOT EXISTS rulet (id INT PRIMARY KEY NOT NULL,productid INT NOT NULL, rtype text NOT NULL,rlength INT ,rtext text)');
    });
}
export function recreateHistoryTable() {
    return new Promise((resolve, reject) => {
        db.transaction(function (tx) {
            tx.executeSql('CREATE TABLE IF NOT EXISTS history (code text PRIMARY KEY  NOT NULL)');
            tx.executeSql('DROP TABLE history');
            tx.executeSql('CREATE TABLE IF NOT EXISTS history (code text PRIMARY KEY  NOT NULL)');
        }, (e) => {
            reject(e)
        }, () => {
            resolve()
        }
        );

    })

}

export function batchInsertHistory(data) {
    const batchSql = data.map(item => {
        return ['INSERT INTO history (code) VALUES (?)', [item]];
    })
    return new Promise((resolve, reject) => {
        db.sqlBatch(batchSql, function () {
            resolve()
        }, function (error) {
            reject(error)
        });
    });

}
export function existHistory(code) {
    return new Promise((resolve, reject) => {
        db.transaction(function (tx) {
            tx.executeSql('SELECT * FROM history where code = ?', [code], function (tx, res) {
                console.log(res.rows.length)
                resolve(res.rows.length > 0)
            }, (e) => {
                console.log(e)
                reject(e)
            });
        });
    });

}

export function recreateProductRuleTable() {
    return new Promise((resolve, reject) => {
        db.transaction(function (tx) {
            tx.executeSql('CREATE TABLE IF NOT EXISTS productrule (id INT PRIMARY KEY NOT NULL, name text, showrule text)');
            tx.executeSql('CREATE TABLE IF NOT EXISTS rulet (id INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL ,productid INT NOT NULL, rtype text NOT NULL,rlength INT ,rtext text)');
            tx.executeSql('DROP TABLE productrule');
            tx.executeSql('DROP TABLE rulet');
            tx.executeSql('CREATE TABLE IF NOT EXISTS productrule (id INT PRIMARY KEY NOT NULL, name text, showrule text)');
            tx.executeSql('CREATE TABLE IF NOT EXISTS rulet (id INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL ,productid INT NOT NULL, rtype text NOT NULL,rlength INT ,rtext text)');
        }, (e) => { reject(e) }, () => { resolve() }
        );
    })

}


export function batchInserRules(products) {
    const sqls = []
    for (let i = 0; i < products.length; i++) {
        const product = products[i];
        sqls.push(['INSERT INTO productrule (id, name, showrule) VALUES (?,?,?)', [i, product.name, product.showrule]]);
        for (let j = 0; j < product.rules.length; j++) {
            const r = product.rules[j];
            sqls.push(['INSERT INTO rulet (productid, rtype, rlength, rtext) VALUES (?,?,?,?)', [i, r.rtype, r.rlength, r.rtext]]);
        }
    }
    return new Promise((resolve, reject) => {
        db.sqlBatch(sqls, () => { resolve() }, (e) => { reject(e) });
    })

}

export function selectProducts(page, pagesize) {
    return new Promise((resolve, reject) => {
        db.transaction(function (tx) {
            tx.executeSql('SELECT * FROM productrule limit ? OFFSET ?', [pagesize, page * pagesize], function (tx, res) {
                const products = []
                for (let i = 0; i < res.rows.length; i++) {
                    const product = res.rows.item(i);
                    products.push(product)
                }
                const pp = []
                for (let i = 0; i < products.length; i++) {
                    const product = res.rows.item(i);
                    const p = new Promise((resolve2, reject2) => {
                        db.transaction(function (tx2) {
                            tx2.executeSql('SELECT * FROM rulet where productid = ?', [product.id], function (tx2, res2) {
                                product.rules = []
                                for (let j = 0; j < res2.rows.length; j++) {
                                    product.rules.push(res2.rows.item(j))
                                }
                                resolve2();
                            }, () => { }, (e) => { reject2(e) });
                        })
                    });
                    pp.push(p)
                }
                Promise.all(pp).then(() => {
                    resolve(products)
                }, (e) => {
                    reject(e)
                });
            });
        }, (e) => {
            reject(e)
        });
    });

}

const key = 'testkeyencode'
const encodeKey = 'testkeyencodexxx'

/**
 * AES加密
 * @param plainText 明文
 * @param keyInBase64Str base64编码后的key
 * @returns {string} base64编码后的密文
 */
export function encryptByAES(plainText, keyInBase64Str) {
    let key = cryptoService.enc.Base64.parse(keyInBase64Str);
    let encrypted = cryptoService.AES.encrypt(plainText, key, {
        mode: cryptoService.mode.ECB,
        padding: cryptoService.pad.Pkcs7,
    });
    // 这里的encrypted不是字符串，而是一个CipherParams对象
    return encrypted.ciphertext.toString(cryptoService.enc.Base64);
}

/**
 * AES解密
 * @param cipherText 密文
 * @param keyInBase64Str base64编码后的key
 * @return 明文
 */
export function decryptByAES(cipherText, keyInBase64Str) {
    let key = cryptoService.enc.Base64.parse(keyInBase64Str);
    // 返回的是一个Word Array Object，其实就是Java里的字节数组
    let decrypted = cryptoService.AES.decrypt(cipherText, key, {
        mode: cryptoService.mode.ECB,
        padding: cryptoService.pad.Pkcs7,
    });

    return decrypted.toString(cryptoService.enc.Utf8);
}

export function increaseUses() {
    return new Promise((resolve, reject) => {
        db.transaction((tx) => {
            tx.executeSql('SELECT * FROM uses where code = ?', [key], (tx, res) => {
                if (res.rows.length > 0) {
                    try {
                        let countText = res.rows.item(0).count
                        countText = decryptByAES(countText, encodeKey)
                        const count = parseInt(countText) + 1;
                        countText = encryptByAES(count.toString(), encodeKey);
                        tx.executeSql('UPDATE uses set count = ? where code = ?', [countText, key], () => {
                            resolve()
                        },()=>{}, (e) => { reject(e) });
                    } catch (e) {
                        reject(e)
                    }
                } else {
                    let countText = '1';
                    countText = encryptByAES(countText, encodeKey);
                    tx.executeSql('INSERT INTO uses (code, count) VALUES (?,?)', [key, countText], () => {
                        resolve()
                    },()=>{}, (e) => { console.log(e); reject(e) });
                }
            });

        }, (e) => { reject(e) }, () => { resolve() })
    });
}

const maxUses = 100;

export function validateUses() {
    return new Promise((resolve, reject) => {
        db.transaction((tx) => {
            tx.executeSql('SELECT * FROM uses where code = ?', [key], (tx, res) => {
                if (res.rows.length > 0) {
                    try {
                        let countText = res.rows.item(0).count
                        countText = decryptByAES(countText, encodeKey);
                        const count = parseInt(countText);
                        if (count < maxUses) {
                            resolve()
                        } else {
                            reject('Max uses reached')
                        }
                    } catch (e) {
                        reject(e)
                    }
                }
            });
        }, () => {
        })
    });
}